#pragma once
#include <vector>
#include "Mutex.hpp"
#include "Sem.hpp"
static const int gcap = 5;

using namespace MutexModule;
using namespace SemModule;

template <typename T>
/**
 * @brief 环形队列类，用于实现生产者-消费者模式。
 *
 * 该类实现了一个线程安全的环形队列，支持多个生产者和多个消费者。
 * 核心功能包括入队（Equeue）和出队（Pop）操作。
 * 使用信号量和互斥锁来保证线程安全，避免数据竞争和死锁。
 *
 * 使用示例：
 *
 * 构造函数参数：
 * - `cap`：队列的容量，默认值为`gcap`。
 *
 * 特殊使用限制或潜在的副作用：
 * - 确保在使用队列之前已经正确初始化信号量和互斥锁。
 * - 队列的容量在创建时确定，之后不可更改。
 */
class RingQueue
{
public:
    RingQueue(int cap = gcap)
        : _cap(cap)
        , _rq(cap)
        , _blank_sem(cap)
        , _p_step(0)
        , _c_step(0)
    {
    }
    void Equeue(const T &in)
    {
        // 生产者
        // 1. 申请信号量，空位置信号量
        _blank_sem.P();
        {
            LockGuard LockGuard(_pmutex);
            // 2. 生产
            _rq[_p_step] = in;
            // 3. 更新下标
            ++_p_step;
            // 4. 维持环形特性
            _p_step %= _cap;
        }
        _data_sem.V();
    }
    void Pop(T *out)
    {
        // 消费者
        // 1. 申请信号量，数据信号量
        _data_sem.P();
        {
            LockGuard LockGuard(_cmutex);
            // 2. 消费
            *out = _rq[_c_step];
            // 3. 更新下标
            ++_c_step;
            // 4. 维持环形特性
            _c_step %= _cap;
        }
        _blank_sem.V();
    }

private:
    std::vector<T> _rq;
    int _cap;

    // 生产者
    Sem _blank_sem;  // 空位置
    int _p_step;
    // 消费者
    Sem _data_sem;  // 数据
    int _c_step;

    // 维护多生产，多消费, 2把锁
    Mutex _cmutex;
    Mutex _pmutex;
};
